_Pragma("once")

#include <string>
#include "SDL.h"

#include "libmath.hpp"

namespace sdl_engine {

class Event {
public:
    virtual ~Event() = default;

    virtual std::string Name() const = 0;
};

class EventQuit: public Event {
public:
    std::string Name() const { return "Event Quit"; }
};

enum class MouseButton {
    Left = SDL_BUTTON_LEFT,
    Right = SDL_BUTTON_RIGHT,
    Middle = SDL_BUTTON_MIDDLE,
    X1 = SDL_BUTTON_X1,
    X2 = SDL_BUTTON_X2
};

class EventMouseButtonDown: public Event {
public:
    EventMouseButtonDown(const Point& position, MouseButton button);

    inline const Point& Position() const { return position_; }
    inline const MouseButton& Button() const { return button_; }

    std::string Name() const { return "Event mouse button down"; }

private:
    Point position_;
    MouseButton button_;
};

class EventMouseButtonUp: public Event {
public:
    EventMouseButtonUp(const Point& position, MouseButton button);

    inline const Point& Position() const { return position_; }
    inline const MouseButton& Button() const { return button_; }

    std::string Name() const { return "Event mouse button up"; }

private:
    Point position_;
    MouseButton button_;
};

class EventMouseMotion: public Event {
public:
    EventMouseMotion(const Point& position, const Point& offset);

    inline const Point& Position() const { return position_; }
    inline const Point& Offset() const { return offset_; }
    std::string Name() const { return "Event mouse motion"; }

private:
    Point position_;
    Point offset_;
};

class EventMouseWheel: public Event {
public:
    EventMouseWheel(int value);

    inline int Value() const { return value_; }

    std::string Name() const { return "Event mouse wheel"; }

private:
    int value_;
};

class EventKeyDown: public Event {
public:
    EventKeyDown(SDL_Keycode key);

    inline SDL_Keycode Key() const { return key_; }

    std::string Name() const { return "Event key down"; }

private:
    SDL_Keycode key_;
};

class EventKeyUp: public Event {
public:
    EventKeyUp(SDL_Keycode key);

    inline SDL_Keycode Key() const { return key_; }

    std::string Name() const { return "Event key up"; }

private:
    SDL_Keycode key_;
};

class EventWindowResize: public Event {
public:
    EventWindowResize(const Size& size);

    inline Size Size() const { return size_; }

    std::string Name() const { return "Event window resize"; }

private:
    sdl_engine::Size size_;
};

class EventTouchFinger: public Event {
public:
    EventTouchFinger(const Point& point,
                     const FPoint& offset,
                     float pressure);

    std::string Name() const { return "Event touch"; }

    inline const Point& GetPosition() const { return position_; }
    inline const FPoint& GetOffset() const { return offset_; }
    inline float GetPressure() const { return pressure_; }

private:
    Point position_;
    FPoint offset_;
    float pressure_;
};

class EventMultiGesture: public Event {
public:
    EventMultiGesture(float thetaOffset,
                      float distOffet,
                      const Point& center,
                      u16 fingerNum);

    std::string Name() const { return "Event multi gesture"; }

    inline float Theta() const { return theta_; }
    inline float Dist() const { return dist_; }
    inline const Point& Center() const { return center_; }
    inline u16 FingerNum() const { return fingerNum_; }

private:
    float theta_;
    float dist_;
    Point center_;
    u16 fingerNum_;
};

}
